import types
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

try:
	import math
	import pygame
	import sys
	from math import ceil
	from pygame.event import Event
	from pygame.locals import *
	from langutils import *
except ImportError, err:
	print err
	sys.exit(2)

'''
Animateable "Interface"
A sprite that inherits this class must do the following:

1. Call Animatable.__init__(self) on its own __init__()
2. Call self.set_anim_params(distance_in_px, duration_in_frames) as
   soon as those params are known
3. Have a move() that sets self.animating to an int direction or zero
4. Have an update() that, if self.animating is true, calls self.slide()
   and then uses the new x and y values

Current directions are set to the arrow keys. Should probably become
their own constants (perhaps stored in utils.py).

Could also create Moveable.py. Or rename Animatable to Movable and
add the move() and r_move() methods right here (direction boundary
variables would have to be set).

Yikes. Pretty much every object uses x & y differently.
Major rework pending.
'''

SLIDE_DURATION = 6
ACCEL_SLIDE_DUR = 2

class Animateable(object):
	def __init__(self):
		object.__init__(self)
		self.x = 0
		self.y = 0
		self.animating = []
		self.end_event = None

	def set_anim_params(self, distance, duration = SLIDE_DURATION):
		self.px_remaining = distance
		self.frames_left = duration
		self.orig_dist_dur = (distance, duration)

	def set_end_event_name(self, name):
		self.end_event = Event(USEREVENT, {'name' : name})

	def slide(self):
		if self.frames_left == 1:
			step = self.px_remaining
		else:
			step = int(ceil(self.px_remaining / self.frames_left))

		if K_UP in self.animating:
			self.y -= step
		if K_RIGHT in self.animating:
			self.x += step
		if K_DOWN in self.animating:
			self.y += step
		if K_LEFT in self.animating:
			self.x -= step
		self.frames_left -= 1
		self.px_remaining -= step
		if not self.px_remaining:
			self.reset()

	def reset(self):
		
		self.animating = []
		(self.px_remaining, self.frames_left) = self.orig_dist_dur
		if self.end_event is not None:
			pygame.event.post(self.end_event)



class AnimateableDiag(Animateable):
	"""
	Animateable objects that can move diagonally

	self.animating comprises of an x and y list within a list
	self.frames_left and self.px_remaining are also [x, y]
	x and y movement are calculated separately
	"""
	def __init__(self):
		Animateable.__init__(self)
		self.animating = [[],[]]

	def set_anim_params(self, distance, duration = SLIDE_DURATION):
		self.px_remaining = [distance, distance]
		self.frames_left = [duration, duration]
		self.orig_dist_dur = (distance, duration)

	def slide(self):
		if self.frames_left[0] == 1:
			step_x = self.px_remaining[0]
		elif self.frames_left[0] <= 0:
			step_x = 0
		else:
			step_x = int(ceil(self.px_remaining[0] / self.frames_left[0]))

		if self.frames_left[1] == 1:
			step_y = self.px_remaining[1]
		elif self.frames_left[1] <= 0:
			step_y = 0
		else:
			step_y = int(ceil(self.px_remaining[1] / self.frames_left[1]))
		
		if K_RIGHT in self.animating[0]:
			self.x += step_x
			self.frames_left[0] -= 1
			self.px_remaining[0] -= step_x
		if K_LEFT in self.animating[0]:
			self.x -= step_x
			self.frames_left[0] -= 1
			self.px_remaining[0] -= step_x

		if K_UP in self.animating[1]:
			self.y -= step_y
			self.frames_left[1] -= 1
			self.px_remaining[1] -= step_y
		if K_DOWN in self.animating[1]:
			self.y += step_y
			self.frames_left[1] -= 1
			self.px_remaining[1] -= step_y

		if self.frames_left[0] <= 0:
			self.reset(0)
		if self.frames_left[1] <= 0:
			self.reset(1)

	def reset(self, d):

		self.animating[d] = []


		self.px_remaining[d] = self.orig_dist_dur[0]

		#shift mod for accelerated scrolling
		if self.mod & KMOD_SHIFT:
			self.frames_left[d] = ACCEL_SLIDE_DUR
		else:
			self.frames_left[d] = self.orig_dist_dur[1]
		
		if self.end_event is not None:
			pygame.event.post(self.end_event)











